Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reusable blocks REST API #2503

Merged
merged 11 commits into from
Oct 6, 2017
Merged

Add reusable blocks REST API #2503

merged 11 commits into from
Oct 6, 2017

Conversation

noisysocks
Copy link
Member

@noisysocks noisysocks commented Aug 22, 2017

Baby's first PR! 👶

This adds the REST API for creating, viewing and editing reusable blocks that @westonruter described in #2081. This API will let us add the ability to turn a static block into a dynamic reusable block (see #1516).

What I did

The TL;DR of it all is:

  • I'm adding a new post type named gb_reusable_block
  • I'm adding three REST API endpoints:
    • GET /wp-json/gutenberg/v1/reusable-blocks - lists all reusable blocks
    • GET /wp-json/gutenberg/v1/reusable-blocks/:uuid - fetches a single reusable block
    • PUT /wp-json/gutenberg/v1/reusable-blocks/:uuid - creates or edits a reusable block
  • A reusable block looks like this:
    {
      "id": "358b59ee-bab3-4d6f-8445-e8c6971a5605",
      "name": "My cool block",
      "content": "<!-- wp:core/paragraph -->\n<p>Hello <strong>World</strong>! How are you?</p>\n<!-- /wp:core/paragraph -->"
    }
    They're stored as posts with post_type set to gb_reusable_block.
    • id is stored in post_name
    • name is stored in post_title
    • content is stored in post_content

How to test

OK. First, make sure you have the JSON Basic Authentication plugin installed, and that your test WordPress environment has pretty URLs enabled.

Now, you can create a block by hitting the PUT endpoint:

$ curl -v -X PUT --user admin:password -H 'Content-type: application/json' -d '{"content":"<!-- wp:core/paragraph -->\n<p>Hello!</p>\n<!-- /wp:core/paragraph -->","name":"My cool block"}' http://vagrant.local/wp-json/gutenberg/v1/reusable-blocks/358b59ee-bab3-4d6f-8445-e8c6971a5605

You'll likely want to change admin:password and http://vagrant.local to match your test WordPress environment.

Now that our block is created, we can fetch it:

$ curl --user admin:password http://vagrant.local/wp-json/gutenberg/v1/reusable-blocks/358b59ee-bab3-4d6f-8445-e8c6971a5605
{"id":"358b59ee-bab3-4d6f-8445-e8c6971a5605","name":"My cool block","content":"<!-- wp:core/paragraph -->\n<p>Hello!</p>\n<!-- /wp:core/paragraph -->"}

We can also list all blocks:

$ curl --user admin:password http://vagrant.local/wp-json/gutenberg/v1/reusable-blocks
[{"id":"358b59ee-bab3-4d6f-8445-e8c6971a5605","name":"My cool block","content":"<!-- wp:core/paragraph -->\n<p>Hello!</p>\n<!-- /wp:core/paragraph -->"}]

Play around with creating, editing and reading a few different valid and invalid reusable blocks.


cc. @nb @mtias @westonruter

@noisysocks
Copy link
Member Author

For context, I'm working on building out the flow that @jasmussen describes in this comment.

The goal is that users can:

  • Convert a block into a reusable block, and give it a name
  • Convert a reusable block back into a regular block
  • Edit a reusable block within a post and have the changes appear across all posts
  • Insert an existing reusable block into a post
  • Delete an existing reusable block

This is a good place to start with and iterate on as it isn't too technically difficult, it offers a lot of value to users (e.g. one could create a custom HTML block to reuse throughout their blog), and it moves us a step closer to a world where Gutenberg can handle theme customisation.

I'm splitting the overall work into roughly three PRs:

  1. Adding the REST API (that's this one!)
  2. Adding a core/reusable-block block to the editor that can be rendered and edited
  3. Adding UI to the editor for adding, deleting, attaching and detaching reusable blocks

@noisysocks noisysocks mentioned this pull request Sep 4, 2017
adamsilverstein pushed a commit to adamsilverstein/gutenberg that referenced this pull request Sep 7, 2017
@youknowriad
Copy link
Contributor

Thanks for working on this, this is a killer feature.

I'm adding some REST API people as reviewers for a better review.

I don't think the type and the attributes are being saved yet, are they?

@mtias mtias added [Feature] Block API API that allows to express the block paradigm. Framework Issues related to broader framework topics, especially as it relates to javascript labels Sep 26, 2017
@noisysocks
Copy link
Member Author

noisysocks commented Sep 26, 2017

Thanks @youknowriad!

I don't think the type and the attributes are being saved yet, are they?

Ah, I forgot to update this PR's description!

I decided to omit type and attributes in lieu of just having Gutenblock HTML in content. That is, a reusable block now looks like this:

{
  "id": "358b59ee-bab3-4d6f-8445-e8c6971a5605",
  "name": "My cool block",
  "content": "<!-- wp:core/paragraph -->\n<p>Hello <strong>World</strong>! How are you?</p>\n<!-- /wp:core/paragraph -->"
}

This simplifies the client code that works with the API (here and here), since we can just use Gutenberg's parse and serialize functions.

@youknowriad
Copy link
Contributor

@noisysocks Oh great! in that case, this is looking good to me. Might be better to get a REST folk Review and merge.

@westonruter
Copy link
Member

@noisysocks I think it should include the block in the type. Why omit it? Also, I think the block attributes should be made available in parsed form as readonly. We have the parsing logic in PHP so we should use it. Eventually, if we have PHP implementations of the various attribute sources, then they could be included among attributes as well.

@youknowriad
Copy link
Contributor

I think it should include the block in the type. Why omit it? Also, I think the block attributes should be made available in parsed form as readonly.

I personally don't like "duplication" because it means, something could go out of sync easily, and it seems weird to me to store the serialization and a half parsed block in the same structure. I see two options:

  • Keep it as is, store the HTML raw content
  • or Store attributes + block type instead of the raw content.

Unless we have the PHP implementations of the attributes matchers #2751 the first option is the achievable one.

@westonruter
Copy link
Member

@youknowriad That's why I suggest that the type and attributes properties should both be readonly. So it could not go out of sync.

The type is normally readonly in the REST API anyway: https://github.com/WordPress/wordpress-develop/blob/e8e027e7a6c028c0d72cd005ac8426b046583880/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L1766-L1771

@noisysocks
Copy link
Member Author

noisysocks commented Oct 2, 2017

@westonruter The frontend code I wrote didn't use those properties, so I figured we ain't gonna need it. Happy to add them back in as readonly fields. Is there a use case for them that you foresee? Third party API consumers is all that comes to my new-to-Gutenberg mind.

@rmccue
Copy link
Contributor

rmccue commented Oct 3, 2017

The type is normally readonly in the REST API anyway

Post types are immutable because each type has their own specific handling, and changing it would require two controllers working together to handle that. I'm not sure if that's something that needs to be considered for Gutenberg blocks?

@westonruter
Copy link
Member

It just seemed that having a type would make the REST block resources more closely aligned with the other REST resource schemas. True we can add it later, as also adding parsed attributes.

Adds a GET route for reading reusable blocks, and a PUT route for
creating and editing reusable blocks.
The WP_Error wasn't being returned, which meant that a 400 response
would not occur for invalid block PUT requests.
Adds a GET route for browsing reusable blocks.
We don't yet need this functionality, so best to leave it out for now
(YAGNI). On the backend, this lets us not have to use post meta. On the
frontend, it lets us not have to import private parts of the block
serializer and parser.
PHPCS mistakenly thinks that our calls to $this->namespace are us using
the namespace keyword, which is not available in PHP 5.2. The fix is to
explicitly ignore the lint error.
Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get this merged to move forward with the other PR. I'm fine revisiting the API once we get the server side attribute parsing.

Nice work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. Framework Issues related to broader framework topics, especially as it relates to javascript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants